import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PGraphics;

/**
 * Draw rounded rectangles. This class creates a shape so that it will be
 * affected by fill() and stroke().
 */
public class RRect {

	/*
	 * You need the graphic context in order to access rectMode and ellipseMode
	 */
	PGraphics g;
	PApplet parent;

	RRect(PApplet applet) {
		g = applet.g;
		parent = applet;
	}

	void rrect(float x, float y, float w, float h, float r) {
		rrect(x, y, w, h, r, r);
	}

	/**
	 * Draw a rectangle with round corners of different radii.
	 * 
	 * @param x
	 *            left/center x coordinate, depending on rectMode
	 * @param y
	 *            top/center y coordinate, depending on rectMode
	 * @param w
	 *            width/right corner of rectangle, depending on rectMode
	 * @param h
	 *            height/bottom corner of rectangle, depending on rectMode
	 * @param rx
	 *            x-radius of rounded corners
	 * @param ry
	 *            y-radius of rounded corners
	 */
	void rrect(float x, float y, float w, float h, float rx, float ry) {
		int rMode = g.rectMode;
		int eMode = g.ellipseMode; // save ellipse mode
		parent.ellipseMode(PConstants.CORNER); // the math is easier in this
												// mode
		if (rMode == PConstants.CENTER) {
			x = (float) (x - w / 2.0);
			y = (float) (y - h / 2.0);
		} else if (rMode == PConstants.CORNERS) {
			w = w - x;
			h = h - y;
		} else if (rMode == PConstants.RADIUS) {
			x = x - w;
			y = y - h;
			w *= 2;
			h *= 2;
		}

		parent.beginShape();
		// top line
		parent.vertex(x + rx, y);
		parent.vertex(x + w - rx, y);

		// top left curve
		parent.curveVertex(x + w - rx, y);
		parent.curveVertex(x + w - rx
				+ (rx * PApplet.cos(PApplet.radians(300))), y + ry
				+ (ry * PApplet.sin(PApplet.radians(300))));
		parent.curveVertex(x + w - rx
				+ (rx * PApplet.cos(PApplet.radians(330))), y + ry
				+ (ry * PApplet.sin(PApplet.radians(330))));
		parent.curveVertex(x + w, y + ry);
		parent.curveVertex(x + w, y + ry);

		// right line
		parent.vertex(x + w, y + h - ry);

		// bottom right curve
		parent.curveVertex(x + w, y + h - ry);
		parent.curveVertex(
				x + w - rx + (rx * PApplet.cos(PApplet.radians(30))), y + h
						- ry + (ry * PApplet.sin(PApplet.radians(30))));
		parent.curveVertex(
				x + w - rx + (rx * PApplet.cos(PApplet.radians(60))), y + h
						- ry + (ry * PApplet.sin(PApplet.radians(60))));
		parent.curveVertex(x + w - rx, y + h);
		parent.curveVertex(x + w - rx, y + h);

		// bottom line
		parent.vertex(x + rx, y + h);

		// bottom left curve
		parent.curveVertex(x + rx, y + h);
		parent.curveVertex(x + rx + (rx * PApplet.cos(PApplet.radians(120))), y
				+ h - ry + (ry * PApplet.sin(PApplet.radians(120))));
		parent.curveVertex(x + rx + (rx * PApplet.cos(PApplet.radians(150))), y
				+ h - ry + (ry * PApplet.sin(PApplet.radians(150))));
		parent.curveVertex(x, y + h - ry);
		parent.curveVertex(x, y + h - ry);

		// left line
		parent.vertex(x, y + ry);

		// top left curve
		parent.curveVertex(x, y + ry);
		parent.curveVertex(x + rx + (rx * PApplet.cos(PApplet.radians(210))), y
				+ ry + (ry * PApplet.sin(PApplet.radians(210))));
		parent.curveVertex(x + rx + (rx * PApplet.cos(PApplet.radians(240))), y
				+ ry + (ry * PApplet.sin(PApplet.radians(240))));
		parent.curveVertex(x + rx, y);
		parent.curveVertex(x + rx, y);
		parent.endShape(PConstants.CLOSE);
		parent.ellipseMode(eMode); // restore ellipse mode
	}
}